﻿using Common;
using GlobalVariableModuleCs;
using ImageSourceModuleCs;
using MvCamCtrl.NET;
using NewDevice;
using NewDevice.RS232;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Xml;
using Vision001.Base;
using Vision001.Helper;
using Vision001.Models;
using Vision001.Procedure;
using Vision001.Views;
using VM.Core;
using VM.PlatformSDKCS;
using VMControls.WPF.Release;

using VmRenderControl = VMControls.WPF.Release;

namespace Vision001.ViewModels
{
    //绑定到日志方法
    public delegate void updateHandler(string msg, LogLevel level = LogLevel.Info, [CallerMemberName] string propertyName = null);

    public delegate void updatedataHandler(int num, bool isOK);

    public delegate void StartHandler(object obj);

    public delegate void FocusHandler();

    public delegate void ResetHandler(object obj);

    public delegate void EmsStopHandler(object obj);

    public class OperaViewModel : NotifyPorperChanged
    {
        private OperateView _operateView;
        private StationSatus _stationSatus;
        public static updateHandler updatemessage;
        public static FocusHandler focus;
        public static updatedataHandler updatedata;
        private CancellationTokenSource _commonIoSource;
        public static StartHandler _Start;
        public static EmsStopHandler EmsStop;
        public static ResetHandler _Reset;

        public OperaViewModel(OperateView operateView)
        {
            _stationSatus = StationSatus.空闲;
            _operateView = operateView;
            WorkStationModels = new ObservableCollection<WorkStationModel>();

            WindowLoadedCommand = new Command() { ExeAction = new Action<object>(WindowLoadedcmd) };
            WindowClosingCommand = new Command() { ExeAction = new Action<object>(WindowClosingCmd) };
            StartUpCommand = new Command() { ExeAction = new Action<object>(StartUpCmd) };
            ResetCommand = new Command() { ExeAction = new Action<object>(ResetCmd) };
            OneStepCommand = new Command() { ExeAction = new Action<object>(OneStepCmd) };
            HomeViewModel.UpdateConfigName -= ChangeNowConfigNane;
            HomeViewModel.UpdateConfigName += ChangeNowConfigNane;
            HomeViewModel._Start = StartUpCmd;
            HomeViewModel._Reset = ResetCmd;
            HomeViewModel.EmsStop = EmgStopCmd;
            TestMethod.UpdateWorkStation += UpdateWorkStation;
        }

        #region 初始化命令以及属性

        private Command _changeStatusCommand;

        public Command ChangeStatusCommand
        {
            set
            {
                _changeStatusCommand = value;
            }
            get { return _changeStatusCommand; }
        }

        private Command _startupCommand;

        public Command StartUpCommand
        {
            set
            {
                _startupCommand = value;
            }
            get { return _startupCommand; }
        }

        private Command _resetCommand;

        public Command ResetCommand
        {
            set
            {
                _resetCommand = value;
            }
            get { return _resetCommand; }
        }

        private Command _onestepCommand;

        public Command OneStepCommand
        {
            set
            {
                _onestepCommand = value;
            }
            get { return _onestepCommand; }
        }

        private Command _windowLoadedCommand;

        /// <summary>
        /// 界面加载
        /// </summary>
        public Command WindowLoadedCommand
        {
            set
            {
                _windowLoadedCommand = value;
            }
            get { return _windowLoadedCommand; }
        }

        private Command _windowClosingCommand;

        /// <summary>
        /// 界面退出
        /// </summary>
        public Command WindowClosingCommand
        {
            set
            {
                _windowClosingCommand = value;
            }
            get { return _windowClosingCommand; }
        }

        private ObservableCollection<WorkStationModel> _workStationModels;

        public ObservableCollection<WorkStationModel> WorkStationModels
        {
            set
            {
                _workStationModels = value;
                this.SetProperty();
            }
            get { return _workStationModels; }
        }

        #endregion 初始化命令以及属性

        #region 绑定方法

        /// <summary>
        /// 单步执行方法
        /// </summary>
        /// <param name="obj"></param>
        private async void OneStepCmd(object obj)
        {
        }

        /// <summary>
        /// 急停方法
        /// </summary>
        /// <param name="obj"></param>
        public void EmgStopCmd(object obj)
        {
        }

        /// <summary>
        /// 暂停方法
        /// </summary>
        /// <param name="obj"></param>
        public void ResetCmd(object obj)
        {
            Global._PqwIoCommon.SetDO((int)CommonIODefineDo.红灯, false);
            _commonIoSource.Cancel();
            //挡板气缸升
            Global._PqwIoCommon.SetDO((int)CommonIODefineDo.挡板气缸, false);
            //复位
            Global.RobotStatus = "等待";
            Global.RobotCode = "";
            Global.TestRobotIsOK = false;
            Global.isRunning = false;
            //发送上游要料信号
            Global._PqwIoCommon.SetDO((int)CommonIODefineDo.上游要料信号, false);
        }

        /// <summary>
        /// 图片转化成VM专用的图片格式
        /// </summary>
        /// <param name="pdata"></param>
        /// <param name="frame"></param>
        /// <returns></returns>
        private static ImageBaseData CCDToImageBaseData(IntPtr pdata, MyCamera.MV_FRAME_OUT_INFO_EX frame)
        {
            ImageBaseData imageBaseData = new ImageBaseData();
            imageBaseData.Width = frame.nWidth;
            imageBaseData.Height = frame.nHeight;
            imageBaseData.DataLen = frame.nFrameLen;
            if (frame.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
            {
                imageBaseData.Pixelformat = (int)VMPixelFormat.VM_PIXEL_MONO_08;
            }
            else if (frame.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
            {
                imageBaseData.Pixelformat = (int)VMPixelFormat.VM_PIXEL_RGB24_C3;
            }
            else
            {
                imageBaseData.Pixelformat = (int)VMPixelFormat.VM_PIXEL_RGB24_C3;
            }
            imageBaseData.ImageData = new byte[frame.nFrameLen];
            Marshal.Copy(pdata, imageBaseData.ImageData, 0, (int)frame.nFrameLen);
            return imageBaseData;
        }

        /// <summary>
        /// 启动方法
        /// </summary>
        /// <param name="obj"></param>
        public async void StartUpCmd(object obj)
        {
            Global._PqwIoCommon.SetDO((int)CommonIODefineDo.红灯, false);
            if (Global.isRunning)
            {
                UpdateMessage("机台正在运行");
                return;
            }

            _commonIoSource = new CancellationTokenSource();
            await Task.Run(async () =>
            {
                Global.isRunning = true;
                while (!_commonIoSource.IsCancellationRequested)
                {
                    //一整个流程
                    try
                    {
                        //挡板气缸升
                        Global._PqwIoCommon.SetDO((int)CommonIODefineDo.挡板气缸, false);
                        //升起延时
                        Global.isRunning = true;
                        //发送上游要料信号
                        Global._PqwIoCommon.SetDO((int)CommonIODefineDo.上游要料信号, true);

                        Global._PqwIoCommon.GetDI();

                        //等待进板信号
                        if (!Global._PqwIoCommon.GetDI((int)CommonIODefineDi.进板))
                        {
                            await Task.Delay(500);
                            continue;
                        }
                        UpdateMessage("要料成功，开始进板");
                        //电机启动，暂时定为感应到进板信号后启动电机
                        IoMotion.MotionRun();
                        //复位
                        Global.RobotStatus = "等待";
                        Global.RobotCode = "";
                        Global.TestRobotIsOK = false;

                        //固定运动时间，后面加载到配置文件
                        await Task.Delay(2000);
                        IoMotion.MotionStop();
                        await Task.Delay(500);
                        Global._PqwIoCommon.GetDI();
                        if (!Global._PqwIoCommon.GetDI((int)CommonIODefineDi.到位))
                        {
                            UpdateMessage("到位失败", LogLevel.Error);
                            UpdateMessage("到位失败，请取板");

                            break; ;
                        }
                        Global._PqwIoCommon.SetDO((int)CommonIODefineDo.上游要料信号, false);
                        //到位之后执行检测流程
                        await Task.Delay(2000);
                        ProcessInfoList processInfoList = VmSolution.Instance.GetAllProcedureList();//所有的流程,默认1000个，根据需求转化

                        VmProcedure procedure = VmSolution.Instance[processInfoList.astProcessInfo[0].strProcessName] as VmProcedure;

                        ImageSourceModuleTool iamgeSource = (ImageSourceModuleTool)VmSolution.Instance["流程1.图像源1"];
                        ImageSourceModuleTool iamgeSource2 = (ImageSourceModuleTool)VmSolution.Instance["流程1.图像源2"];

                        if (await Global._HKcamera.TriggerImage() == 0 && await Global._HKcamera2.TriggerImage() == 0)
                        {
                            VKCameraInfo basecamera = (VKCameraInfo)Global._HKcamera.GetImage();
                            VKCameraInfo basecamera2 = (VKCameraInfo)Global._HKcamera2.GetImage();
                            var image = CCDToImageBaseData(basecamera._pData, basecamera._pFrameInfo);
                            var image2 = CCDToImageBaseData(basecamera2._pData, basecamera2._pFrameInfo);
                            //图像源1
                            iamgeSource.SetImageData(image2);
                            //图像源2
                            iamgeSource2.SetImageData(image);
                            await Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                _operateView.RenderControl.ModuleSource = procedure;
                            }));

                            procedure.Run();

                            GlobalVariableModuleTool global = VmSolution.Instance["全局变量1"] as GlobalVariableModuleTool;

                            var res1 = global.GetGlobalVar("res1");
                            var res2 = global.GetGlobalVar("res2");
                            var res3 = global.GetGlobalVar("res3");
                            var res4 = global.GetGlobalVar("res4");
                            var res5 = global.GetGlobalVar("res5");
                            var res6 = global.GetGlobalVar("res6");

                            //结果处理逻辑
                            string SendRes = "";
                            List<string> stations = new List<string>();
                            if (res1 != "" && res1 != null && res1 != ";" && res2 != "" && res2 != null && res2 != ";"
                                && res3 != "" && res3 != null && res3 != ";"
                                && res4 != "" && res4 != null && res4 != ";"
                                 && res5 != "" && res5 != null && res5 != ";"
                                 && res6 != "" && res6 != null && res6 != ";")
                            {
                                var res = res1.Remove(res1.Length - 1, 1) + res2.Remove(res2.Length - 1, 1) + res3.Remove(res3.Length - 1, 1) + res4.Remove(res4.Length - 1, 1) + res5.Remove(res5.Length - 1, 1) + res6.Remove(res6.Length - 2, 2);
                                string[] Results = res.Split(';');
                                UpdateMessage("Results数量：" + Results.Length.ToString());
                                for (int i = 0; i < Results.Length; i++)
                                {
                                    string[] Res = Results[i].Split(',');
                                    string Code = Res[0];
                                    double X = Convert.ToDouble(Res[1]);
                                    double Y = Convert.ToDouble(Res[2]);

                                    for (int j = 0; j < Global._StationXYConfigs.Count; j++)
                                    {
                                        var dis = CalculateDistance2D(X, Y, Global._StationXYConfigs[j].X, Global._StationXYConfigs[j].Y);
                                        if (CalculateDistance2D(X, Y, Global._StationXYConfigs[j].X, Global._StationXYConfigs[j].Y) < 50)
                                        {
                                            //该工位存在
                                            //先判断该工位是否已经添加
                                            if (!stations.Contains(Global._StationXYConfigs[j].Name))
                                            {
                                                SendRes += Global._StationXYConfigs[j].Name + "," + Code + ";";
                                                stations.Add(Global._StationXYConfigs[j].Name);
                                                break;
                                            }
                                        }
                                    }
                                }
                                UpdateMessage($"工位数量:{stations.Count}");
                                //更新二维码
                                if (SendRes != "")
                                {
                                    Global.RobotCode = SendRes.Remove(SendRes.Length - 1, 1);
                                }
                                else
                                {
                                    Global.RobotCode = SendRes;
                                }
                            }
                            else
                            {
                                Global.RobotCode = SendRes;
                                UpdateMessage("二维码异常！", LogLevel.Error);
                            }
                            image.Dispose();
                        }
                        else
                        {
                            UpdateMessage("相机拍照失败", LogLevel.Error);
                            continue;
                        }
                        //就绪，等测试机要料
                        Global.RobotStatus = "就绪";

                        UpdateMessage("视觉处理完成， 等待测试机要料");
                        //挡板气缸下降
                        Global._PqwIoCommon.SetDO((int)CommonIODefineDo.挡板气缸, true);
                        while (!_commonIoSource.IsCancellationRequested)
                        {
                            if (!_commonIoSource.IsCancellationRequested)
                            {
                                if (Global.TestRobotIsOK)
                                {
                                    //放板,直到出板感应不到

                                    IoMotion.MotionRun();
                                    await Global.server.SendMessagesAsync("joinok");

                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }

                            await Task.Delay(100);
                        }
                        if (_commonIoSource.IsCancellationRequested)
                        {
                            UpdateMessage("退出循环");
                            break;
                        }
                        UpdateMessage("正在出版");
                        Stopwatch stopwatch = Stopwatch.StartNew();
                        while (true)
                        {
                            Global._PqwIoCommon.GetDI();
                            if (Global._PqwIoCommon.GetDI((int)CommonIODefineDi.出版))
                            {
                                Stopwatch stopwatch2 = Stopwatch.StartNew();
                                while (true)
                                {
                                    Global._PqwIoCommon.GetDI();
                                    if (!Global._PqwIoCommon.GetDI((int)CommonIODefineDi.出版))
                                    {
                                        IoMotion.MotionStop();
                                        break;
                                    }
                                    if (stopwatch2.ElapsedMilliseconds > 6000) { IoMotion.MotionStop(); break; }
                                }
                                break;
                            }
                            //最大出版时间
                            if (stopwatch.ElapsedMilliseconds > 6000) { IoMotion.MotionStop(); break; }
                        }
                        Global._PqwIoCommon.SetDO((int)CommonIODefineDo.上游要料信号, false);
                        //挡板气缸升
                        Global._PqwIoCommon.SetDO((int)CommonIODefineDo.挡板气缸, false);
                        //出版完成，
                        //复位
                        Global.RobotStatus = "等待";
                        Global.RobotCode = "";
                        Global.TestRobotIsOK = false;
                        UpdateMessage("发送进板信号，等待中");
                    }
                    catch (Exception e)
                    {
                        Global.RobotStatus = "等待";
                        Global.RobotCode = "";
                        Global.TestRobotIsOK = false;
                        Global.isRunning = false;
                        IoMotion.MotionStop();
                        UpdateMessage(e.Message, LogLevel.Error);
                        UpdateMessage("出现异常，中止自动流程", LogLevel.Error);
                        Global._PqwIoCommon.SetDO((int)CommonIODefineDo.红灯, true);
                        break;
                    }
                    await Task.Delay(2000);
                }
                UpdateMessage("自动循环结束");
                //复位
                Global.RobotStatus = "等待";
                Global.RobotCode = "";
                Global.TestRobotIsOK = false;
                Global.isRunning = false;
                //发送上游要料信号
                Global._PqwIoCommon.SetDO((int)CommonIODefineDo.上游要料信号, false);
            });
        }

        // 计算二维点距离
        public static double CalculateDistance2D(double x1, double y1, double x2, double y2)
        {
            double dx = x2 - x1;
            double dy = y2 - y1;
            return Math.Sqrt(dx * dx + dy * dy);
        }

        /// <summary>
        /// 更新读取到的值
        /// </summary>
        /// <param name="id"></param>
        /// <param name="v1"></param>
        /// <param name="v2"></param>
        /// <param name="v3"></param>
        public void UpdateWorkStation(int id, string v1, string v2, string v3, bool res)
        {
        }

        /// <summary>
        /// 界面加载的时候使用的方法
        /// </summary>
        /// <param name="obj"></param>
        /// <exception cref="NotImplementedException"></exception>
        private void WindowLoadedcmd(object obj)
        {
            //_commonIoSource = new CancellationTokenSource();
            if (Global._Config == null)
            {
            }
            else
            {
            }
        }

        /// <summary>
        /// 界面退出方法
        /// </summary>
        /// <param name="obj"></param>
        private void WindowClosingCmd(object obj)
        {
            //挡板气缸升
            Global._PqwIoCommon.SetDO((int)CommonIODefineDo.挡板气缸, false);
            //复位
            Global.RobotStatus = "等待";
            Global.RobotCode = "";
            Global.TestRobotIsOK = false;
            Global.isRunning = false;
            _commonIoSource.Cancel();
        }

        /// <summary>
        /// 其他界面修改配置名
        /// </summary>
        /// <param name="name"></param>
        public void ChangeNowConfigNane(string name)
        {
        }

        #endregion 绑定方法

        #region 通用方法

        private void UpdateMessage(string msg, LogLevel logLevel = LogLevel.Info)
        {
            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                updatemessage?.Invoke(msg, logLevel);
            }));
        }

        #endregion 通用方法
    }
}